/**
 * 
 */
package co.fitstart.market.service.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.demo2do.core.persistence.GenericDaoSupport;
import com.demo2do.core.service.impl.GenericServiceImpl;

import co.fitstart.entity.coupon.Coupon;
import co.fitstart.entity.user.User;
import co.fitstart.entity.user.UserAccount;
import co.fitstart.entity.user.WechatAccount;
import co.fitstart.entity.user.inbody.InbodyRecord;
import co.fitstart.market.Constant;
import co.fitstart.market.service.UserService;

/**
 * @author downpour
 * @author lute
 *
 */
@Service("userService")
public class UserServiceImpl extends GenericServiceImpl<User> implements UserService {
    
    @Autowired
    private GenericDaoSupport genericDaoSupport;
    
    /**
     * get user by mobile
     * 
     * @param mobile
     * @return
     */
    private User getUserByMobile(String mobile) {
        String querySentence = "FROM User user WHERE user.mobile = :mobile AND user.disabled = false";
        return genericDaoSupport.searchForObject(querySentence, "mobile", mobile, User.class);
    }
    
    /**
     * 
     * @param openid
     * @return
     */
    private WechatAccount getWechatAccount(String openid) {
        return genericDaoSupport.searchForObject("FROM WechatAccount WHERE openid = :openid", "openid", openid, WechatAccount.class);
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.mobile.service.UserService#getUserbyMobile(java.lang.String)
     */
    public User getUser(String mobile) {
        return this.getUserByMobile(mobile);
    }
    
    /* (non-Javadoc)
     * @see co.fitstart.weixin.service.UserService#getUser(java.lang.String)
     */
    public User getUserByOpenId(String openid) {
        String querySentence = "FROM User user WHERE user.openid = :openid AND user.disabled = false";
        return genericDaoSupport.searchForObject(querySentence, "openid", openid, User.class);
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.mobile.service.UserService#getUserAccount(java.lang.String, java.lang.String)
     */
    public UserAccount getUserAccount(String name, String value) {
        
        String querySentence = "FROM UserAccount userAccount WHERE userAccount.name = :name AND userAccount.value = :value";
        
        Map<String, Object> parameters = new HashMap<String, Object>(3);
        parameters.put("name", name);
        parameters.put("value", value);
        
        return genericDaoSupport.searchForObject(querySentence, parameters, UserAccount.class);
        
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.mobile.service.UserService#createUserAccount(co.fitstart.entity.user.UserAccount, co.fitstart.entity.user.WechatAccount)
     */
    public void createUserAccount(UserAccount userAccount, WechatAccount wechatAccount) {

        // create user account
        genericDaoSupport.save(userAccount);
        
        // create wechat account if not exit
        String openid = userAccount.getName();
        if(this.getWechatAccount(openid) == null) {
            genericDaoSupport.save(wechatAccount);
        }
    }
    
    /**
     * 
     * @param mobile
     * @return
     */
    @SuppressWarnings("unchecked")
    private List<InbodyRecord> listInbodyRecords(String mobile) {
        return genericDaoSupport.searchForList("FROM InbodyRecord WHERE disabled = false AND mobile = :mobile", "mobile", mobile);
    }
    
    /**
     * 
     * @param mobile
     * @return
     */
    @SuppressWarnings("unchecked")
    private List<Coupon> listCoupons(String mobile, String openid) {
        String sentence = "FROM Coupon coupon WHERE coupon.identification = :mobile";
        Map<String, Object> parameters = new HashMap<String, Object>();
        parameters.put("mobile", mobile);
        
        if(StringUtils.isNotEmpty(openid) && StringUtils.isNoneEmpty(openid)) {
            sentence = sentence + " OR coupon.openid = :openid";
            parameters.put("openid", openid);
        }
        
        return genericDaoSupport.searchForList(sentence, parameters);
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.mobile.service.UserService#login(java.lang.String, java.lang.String, java.lang.String, boolean)
     */
    public UserAccount login(String mobile, String openid, String accountId, boolean isEmail) {
        
        User user = this.getUserByMobile(mobile);
        
        // if user is empty, create a new user
        if(user == null) {
            user = new User(mobile, isEmail);
            genericDaoSupport.save(user);
        }
        
        // if openid exit, load userAccount by openid, bind userAccount's user and update user by wechatAccount info
        if(StringUtils.isNotEmpty(openid) && StringUtils.isNoneEmpty(openid)) {
            
            UserAccount openidUserAccount = this.getUserAccount(Constant.USER_ACCOUNT_WECHAT_KEY, openid);
            if(openidUserAccount != null) {
                openidUserAccount.bind(user);
                genericDaoSupport.update(openidUserAccount);
            }
            
            WechatAccount wechatAccount = this.getWechatAccount(openid);
            if(wechatAccount != null) {
                user.wechat(wechatAccount);
                genericDaoSupport.update(user);
            }
        }
        
        // if accountId is empty, create a new mobile userAccount and bind user
        UserAccount mobileUserAccount = this.getUserAccount(Constant.USER_ACCOUNT_MOBILE_KEY, mobile);
        if(mobileUserAccount == null) {
            mobileUserAccount = new UserAccount(Constant.USER_ACCOUNT_MOBILE_KEY, mobile);
            genericDaoSupport.save(mobileUserAccount.bind(user));
        }else {
            genericDaoSupport.update(mobileUserAccount.bind(user));
        }
        
        // if same mobile's inbodyRecords not null, bind user inbody records
        List<InbodyRecord> inbodyRecords = this.listInbodyRecords(mobile);
        
        if(CollectionUtils.isNotEmpty(inbodyRecords)) {
            for(InbodyRecord inbodyRecord : inbodyRecords) {
                genericDaoSupport.update(inbodyRecord.bindUser(user));
            }
        }
        
        // if same mobile's coupons not null, bind user coupons
        List<Coupon> coupons = this.listCoupons(mobile, openid);
        
        if(CollectionUtils.isNotEmpty(coupons)) {
            for(Coupon coupon : coupons) {
                genericDaoSupport.update(coupon.bindUser(user.getId()));
            }
        }
        
        return mobileUserAccount;
    }
}
